<?php
/*
 * @Author: CHINAKAIYUAN<sunkaiyuan@namenode.cn>
 * @Date: 2022-02-02 19:42:06
 * @LastEditTime: 2023-10-20 13:14:47
 * @LastEditors: 孙开源 && sunkaiyuan@namenode.cn
 * @Description: 
 */

namespace App\Repositories;

use App\Models\Department;
use App\Models\FinanceBalance;
use App\Models\FinanceDepartment;
use App\Models\FinanceVoucher;
use App\Models\FinanceVoucherDetails;
use App\Models\Subject;
use Illuminate\Database\Eloquent\Model;

/**
 * Summary of FinanceVoucherRepository
 * @property FinanceVoucher $model
 * @property FinanceVoucherDetails $detail
 * @property Subject $subject
 * @property FinanceBalance $balance
 * @author sunkaiyuan
 */
class FinanceVoucherRepository extends Repositories
    {

    protected $relation_models = ['status', 'creator', 'updator', 'attachments', 'details' => ['material', 'company', 'department', 'subject', 'employee']];

    public function boot(FinanceVoucher $model, FinanceVoucherDetails $detail, Subject $subject, FinanceBalance $balance)
        {
        $this->model   = $model;
        $this->detail  = $detail;
        $this->subject = $subject;
        $this->balance = $balance;
        }

    protected function RemoveVoucher($model)
        {
        $voucher = $model instanceof FinanceVoucher ? $model : $model->voucher;
        if ($voucher) {
            if ($voucher->status_id != 0) {
                fail("凭证【{$voucher->code}】已{$voucher->status->name}，禁止操作！！");
                }
            $voucher->details->filter(function ($v)
                {
                $v->delete();
                });
            $voucher->delete();
            }
        }

    /**
     * Summary of CreateVoucher
     * @param mixed $billdate //单据日期
     * @param mixed $trade_id   //交易抬头
     * @param mixed $details    //凭证明细
     * @param mixed $id //单据id
     * @param mixed $currency_id    //币种
     * @param mixed $rate    //汇率
     * @return mixed
     * @author sunkaiyuan
     */
    protected function CreateVoucher($billdate, $trade_id, $details, $model = null, $id = 0, $currency_id = 1, $rate = 1)
        {
        $debit_invoice_amount = $credit_invoice_amount = $debit_amount = $credit_amount = 0;

        $details = array_map(function ($detail) use ($billdate, $trade_id, $currency_id, &$debit_amount, &$credit_amount, &$debit_invoice_amount, &$credit_invoice_amount, $rate)
            {
            $detail['currency_id'] = $currency_id;
            $detail['trade_id']    = $trade_id;
            $detail['rate']        = $rate;
            $detail['billdate']    = date("Y-m-d", strtotime($billdate));
            $debit_amount += $detail['debit_amount'] * $rate;
            $credit_amount += $detail['credit_amount'] * $rate;
            $debit_invoice_amount += $detail['debit_invoice_amount'];
            $credit_invoice_amount += $detail['credit_invoice_amount'];
            return $detail;
            }, $details);
        if ($debit_amount - $credit_amount >= 0.01) {
            fail('借贷方向不平');
            }
        //金额是0的，并且是编辑的删除凭证
        if ($id > 0) {
            $voucher = $this->whereId($id)->first();
            if ($voucher->status_id != 0) {
                fail("凭证【{$voucher->code}】已审核！禁止编辑！");
                }
            }
        else {
            //$id<=0  $debit_amount==0  直接返回。金额为0的凭证，不需要保存！
            // if ($debit_amount == 0 && $debit_invoice_amount + $credit_invoice_amount == 0) {
            //     return;
            //     }
            }
        //获取指定信息
        $source_model = $model != null ? $model::class : "";
        $source_key   = $model != null ? $model->getVoucherkey() : "";
        $source_value = $model != null ? $model->{$source_key} : "";
      
        $voucher = $this->autosave([
            'billdate'      => $billdate,
            'id'            => $id,
            'trade_id'      => $trade_id,
            'currency_id'   => $currency_id,
            'debit_amount'  => $debit_amount,
            'credit_amount' => $credit_amount,
            'source_model'  => $source_model,
            'source_value'  => $source_value,
            'source_key'    => $source_key,
            'rate'          => $rate,
            'details'       => $details
        ]);
        //保存code
        $voucher->details->filter(function ($detail) use ($voucher)
            {
            $detail->code = $voucher->code;
            $detail->save();
            }); 
        return $voucher;
        }
    /**
     * Summary of auditVoucher
     * @param mixed $id
     * @param mixed $isaudit
     * @return mixed
     * @author sunkaiyuan
     */
    protected function auditVoucher($id, $isaudit = true)
        {

        $voucher_data = $id instanceof Model ? $id : $this->whereId($id)->first();
        if ($voucher_data) {
            if ($voucher_data->status_id != ($isaudit ? 0 : 1)) {
                fail("凭证状态修改失败！当前状态[{$voucher_data->status->name}]");
                }
            // $year  = date("Y", strtotime($voucher_data->billdate));
            // $month = date("m", strtotime($voucher_data->billdate));

            // $voucher_data->details->filter(function ($detail) use ($month, $year, $isaudit)
            //     {
            //     //反审 值减去
            //     $debit_amount  = $isaudit ? $detail->debit_amount : (0 - $detail->debit_amount);
            //     $credit_amount = $isaudit ? $detail->credit_amount : (0 - $detail->credit_amount);

            //     $debit_invoice_amount  = $isaudit ? $detail->debit_invoice_amount : (0 - $detail->debit_invoice_amount);
            //     $credit_invoice_amount = $isaudit ? $detail->credit_invoice_amount : (0 - $detail->credit_invoice_amount);


            //     $debit_quantity  = $isaudit ? $detail->debit_quantity : (0 - $detail->debit_quantity);
            //     $credit_quantity = $isaudit ? $detail->credit_quantity : (0 - $detail->credit_quantity);
            //     // $detail
            //     $data         = [
            //         'date'          => $year . $month,
            //         'year'          => $year,
            //         'month'         => $month,
            //         'subject_id'    => $detail->subject_id ?? 0,
            //         'empoyee_id'    => $detail->empoyee_id ?? 0,
            //         'department_id' => $detail->department_id ?? 0,
            //         'company_id'    => $detail->company_id ?? 0,
            //         'material_id'   => $detail->material_id ?? 0,
            //         'type_id'       => $detail->type_id ?? 0,
            //         // 'color_id'      => $detail->color_id ?? 0,
            //         // 'lot_id'        => $detail->lot_id ?? 0,
            //         // 'dyelot'        => $detail->dyelot ?? '',
            //     ];
            //     $balance_data = $this->balance->firstOrCreate($data);


            //     //更新科目余额表
            //     $this->updateSubject($balance_data, $debit_amount, $credit_amount, $debit_quantity, $credit_quantity, $debit_invoice_amount, $credit_invoice_amount);
            //     //更新父科目余额表
            //     $this->createParentBalance($year, $month, $detail->subject_id, $debit_amount, $credit_amount, $debit_quantity, $credit_quantity);

            //     });
            $voucher_data->details->filter(function ($detail) use ($isaudit)
                {
                auditSave($detail, $isaudit);
                });
            // 模型提供审核操作！审核！ 
            if ($isaudit && $voucher_data->source) {
                if (method_exists($voucher_data->source, "finance"))
                    $voucher_data->source->finance($voucher_data->source, $voucher_data);
                else
                    fail("凭证模型错误！没有对样的财务模型方法finance！请联系管理员！");
                }
            auditSave($voucher_data, $isaudit);
            //反审核调用 回调通知
            if (!$isaudit && $voucher_data->source) {
                if (method_exists($voucher_data->source, "nofinance"))
                    $voucher_data->source->nofinance($voucher_data->source, $voucher_data);
                else
                    fail("凭证模型错误！没有对样的财务模型方法nofinance！请联系管理员！");
                }
            return $voucher_data;
            }
        }

    protected function createParentBalance($year, $month, $subject_id, $debit_amount, $credit_amount, $debit_quantity, $credit_quantity)
        {
        $parent_subject_id = substr($subject_id, 0, strlen($subject_id) - 2);
        if (strlen($parent_subject_id) >= 4) {
            $data         = [
                'date'       => $year . $month,
                'year'       => $year,
                'month'      => $month,
                'subject_id' => $parent_subject_id,
            ];
            $balance_data = $this->balance->firstOrCreate($data);
            $this->updateSubject($balance_data, $debit_amount, $credit_amount, $debit_quantity, $credit_quantity);
            $this->createParentBalance($year, $month, $parent_subject_id, $debit_amount, $credit_amount, $debit_quantity, $credit_quantity);
            }
        }
    protected function updateSubject($balance_data, $debit_amount, $credit_amount, $debit_quantity, $credit_quantity, $debit_invoice_amount = 0, $credit_invoice_amount = 0)
        {
        if ($balance_data) {
            $balance_data->debit_amount += $debit_amount;
            $balance_data->credit_amount += $credit_amount;

            $balance_data->debit_quantity += $debit_quantity;
            $balance_data->credit_quantity += $credit_quantity;

            $balance_data->debit_invoice_amount += $debit_invoice_amount;
            $balance_data->credit_invoice_amount += $credit_invoice_amount;
            $balance_data->save();
            }
        }
    /**
     * 合成凭证数据
     * @param mixed $subject_id 科目编码
     * @param mixed $summary    摘要
     * @param mixed $debit_amount   借方金额
     * @param mixed $credit_amount  贷方金额
     * @param mixed $auxiliary  辅助字段 产品，部门，员工，颜色，缸号，数量...
     * @return mixed
     * @author sunkaiyuan
     */
    protected function mergeVoucher($subject_id, $summary, $debit_amount, $credit_amount = 0, $auxiliary = [], $id = 0, $is_tax = 0)
        {
        $subject_data = $this->subject->whereId($subject_id)->first();
        $accounting   = explode(",", $subject_data->accounting);

        if (is_numeric($auxiliary['financedepartment_id'] ?? "") && $auxiliary['financedepartment_id'] > 0) {
            $auxiliary['department_id'] = $auxiliary['financedepartment_id'];
            }
        else
            if (($auxiliary['department_id'] ?? 0) != 0) {
                //替换成财务结算部门
                $auxiliary['department_id'] = Department::whereId($auxiliary['department_id'])->value("financedepartment_id");
                }

        if (in_array(1, $accounting) && ($auxiliary['department_id'] ?? 0) == 0) {
            fail("科目[{$subject_data['full_name']}]需要部门辅助字段！");
            }
        if (in_array(2, $accounting) && ($auxiliary['company_id'] ?? 0) == 0) {
            fail("科目[{$subject_data['full_name']}]需要往来辅助字段！");
            //1122 应收
            }


        if (in_array(3, $accounting) && ($auxiliary['employee_id'] ?? 0) == 0) {
            fail("科目[{$subject_data['full_name']}]需要员工辅助字段！");
            }


        if (in_array(4, $accounting) && ($auxiliary['material_id'] ?? 0) == 0) {
            fail("科目[{$subject_data['full_name']}]需要物料辅助字段！");
            }
        $debit_invoice_amount = $credit_invoice_amount = $invoice_amount = 0;
        if (($auxiliary['company_id'] ?? 0) != 0) {
            $debit_invoice_amount  = $subject_id == '1122' ? ($auxiliary['invoice_amount'] ?? (($debit_amount == 0 ? (0 - $credit_amount) : $debit_amount) * $is_tax)) : 0;
            $credit_invoice_amount = $subject_id == '2202' ? ($auxiliary['invoice_amount'] ?? (($credit_amount == 0 ? (0 - $debit_amount) : $credit_amount) * $is_tax)) : 0;
            $invoice_amount        = ($debit_invoice_amount - $credit_invoice_amount) * CompanyRepository::whereId($auxiliary['company_id'])->first()->finance_id;
            }
        return [
            'subject_id'            => $subject_id,
            //科目
            'summary'               => $summary,
            //摘要
            'debit_amount'          => $debit_amount,
            //借方金额
            'credit_amount'         => $credit_amount,
            //贷方金额
            //产品
            'material_id'           => $auxiliary['material_id'] ?? 0,
            'type_id'               => $auxiliary['type_id'] ?? 0,
            'color_id'              => $auxiliary['color_id'] ?? 0,
            'lot_id'                => $auxiliary['lot_id'] ?? 0,
            'dyelot'                => $auxiliary['dyelot'] ?? '',
            'color_name'            => $auxiliary['color_name'] ?? '',
            'craft'                 => $auxiliary['craft'] ?? "",
            'custno'                => $auxiliary['custno'] ?? "",
            'auxiliary_quantity'    => $auxiliary['auxiliary_quantity'] ?? 0,
            'company_id'            => $auxiliary['company_id'] ?? 0,
            //往来
            'department_id'         => $auxiliary['department_id'] ?? 0,
            //部门
            'employee_id'           => $auxiliary['employee_id'] ?? 0,
            //员工
            'amount'                => ($debit_amount - $credit_amount) * $subject_data->direct_id,
            //数量
            'debit_quantity'        => $debit_amount > 0 ? ($auxiliary['quantity'] ?? 0) : 0,
            //数量
            'credit_quantity'       => $credit_amount > 0 ? ($auxiliary['quantity'] ?? 0) : 0,
            'debit_invoice_amount'  => $debit_invoice_amount,
            'credit_invoice_amount' => $credit_invoice_amount,
            'invoice_amount'        => $invoice_amount,
            'unit_id'               => $auxiliary['unit_id'] ?? 0,
            //数量
            'quantity'              => $auxiliary['quantity'] ?? 0,//出库数
            'se_quantity'           => $auxiliary['se_quantity'] ?? 0,//结算数
            'mi_quantity'           => $auxiliary['mi_quantity'] ?? 0,
            'price'                 => $auxiliary['price'] ?? 0,
            'id'                    => $id,
        ];
        }
    }